約 4,333,217 件
https://w.atwiki.jp/bambooflow/pages/283.html
フォンシェーディング - フラグメントシェーダでのライティング 注意:ここでかかれている内容は、本来のフォンシェーディングという用語に対して使い方が間違っているかもしれませんが、ここでは、フラグメントシェーダでのライティングをフォンシェーディングと呼ぶことにします。 フォンシェーディング - フラグメントシェーダでのライティングフォンシェーディング(Phong shading)について 照明モデル 実装 Blinn-Phongシェーディング ダウンロード サンプルは白の光源が物体のまわりをぐるぐる回ります。 環境 OpenGL 3.3 GLUT(freeglut) - 2.6.0 GLEW - 1.5.7 GLM - 0.9.0.6 フォンシェーディング(Phong shading)について フォンシェーディングでは、ポリゴン表面の法線ベクトルを頂点の法線ベクトルから線形補間で求めます。(フォン補間) グローシェーディングは頂点シェーダで処理していたのに対して、フォンシェーディングはフラグメントシェーダにより計算します。 ハードウェアによるフォン補間は、ラスタライザに処理された法線ベクトルをフラグメント(ピクセル)ごとの法線ベクトル解釈して計算します。 照明モデル 照明モデルは、グローシェーディング時と同じ計算。 実装 頂点シェーダ #version 330 uniform mat4 u_modelMatrix; // モデル・マトリックス uniform mat4 u_viewMatrix; // ビュー・マトリックス uniform mat4 u_projectionMatrix; // 射影・マトリックス uniform vec3 u_lightPos; // 光源位置 in vec3 a_position; in vec3 a_normal; out vec3 v_P; // eye direction out vec3 v_N; // normal direction out vec3 v_L; // light direction void main(void) { mat4 modelViewMatrix = u_viewMatrix * u_modelMatrix; mat3 n_mat = mat3( transpose( inverse(modelViewMatrix) ) ); // normal Matrix vec3 lightVec = vec3(u_viewMatrix * vec4(u_lightPos.xyz, 1.0)); v_P = vec3(modelViewMatrix * vec4(a_position,1.0)); v_N = normalize(n_mat * a_normal); v_L = normalize(lightVec - v_P); gl_Position = u_projectionMatrix * modelViewMatrix * vec4(a_position.xyz, 1.0); } フラグメントシェーダ #version 330 struct MaterialParam { vec4 ambient; vec4 diffuse; vec4 specular; float shininess; }; uniform MaterialParam u_lightMaterial; uniform MaterialParam u_material; in vec3 v_P; in vec3 v_N; in vec3 v_L; out vec4 fragColor; void main(void) { vec3 V = normalize(-v_P); vec3 N = normalize(v_N); // 正規化が必要 vec3 L = normalize(v_L); vec4 ambient = u_lightMaterial.ambient * u_material.ambient; float nDotL = dot(N,L); float diffuseLight = max(nDotL, 0.0); vec4 diffuse = u_lightMaterial.diffuse * u_material.diffuse * diffuseLight; vec3 R = reflect(-L,N); // 反射ベクトルによるスペキュラー float vDotR = pow( max(dot(V,R), 0.0), u_material.shininess ); if (nDotL 0.0) vDotR = 0.0; vec4 specular = u_lightMaterial.specular * u_material.specular * vDotR; // vec3 H = normalize(L+V); // ハーフベクトルによるスペキュラー // float nDotH = pow( max(dot(N,H), 0.0) , u_material.shininess ); // if (nDotL 0.0) nDotH = 0.0; // vec4 specular = u_lightMaterial.specular * u_material.specular * nDotH; fragColor = ambient + diffuse + specular; } メモ1 光源ベクトルLは、頂点シェーダで計算してからフラグメントシェーダに渡しています。 方法としては他に、Lをアプリケーション側で計算してuniformでフラグメントシェーダに直接渡す方法もあります。HW処理負荷を減らすならば後者を選択すべきでしょう。 Blinn-Phongシェーディング Blinn-Phongは物理的に根拠がないですが、経験的にPhongよりも正しいことことがあります。 計算は、反射ベクトルではなく、ハーフベクトルを使います。 シェーダでは、以下のように変更します。 vec3 R = reflect(-L,N); // 反射ベクトルによるスペキュラー float vDotR = pow( max(dot(V,R), 0.0), u_material.shininess ); if (nDotL 0.0) vDotR = 0.0; vec4 specular = u_lightMaterial.specular * u_material.specular * vDotR; ↓ vec3 H = normalize(L+V); // ハーフベクトルによるスペキュラー float nDotH = pow( max(dot(N,H), 0.0) , u_material.shininess ); if (nDotL 0.0) nDotH = 0.0; vec4 specular = u_lightMaterial.specular * u_material.specular * nDotH; ダウンロード glsl_phong00.tgz
https://w.atwiki.jp/www2www/pages/11.html
openglについての何か GL_ARB_texture_non_power_of_two
https://w.atwiki.jp/bambooflow/pages/296.html
フラットシェーディング フラットシェーディングってGLSL使ってどうやるんだろう?って思っていたら以外に簡単でした。 コードとしては、グローシェーディングを少し改良しただけです。 OpenGL 3.x GLUT (freeglut3.7) GLM 0.9.0.6 フラットシェーディングフラットシェーディングの方法 シェーダコード Download フラットシェーディングの方法 varying変数としてバーテックスシェーダからフラグメントシェーダへ渡すcolor情報に""flat"を付けるだけです。 バーテックスシェーダ側 flat out vec4 v_color; フラグメントシェーダ側 flat in vec4 v_color; Cソース側 初期化あたりで次を追加します。 glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); フラットシェーディングでは、頂点間の補間を行わないようにシェーディングするので、プリミティブ(三角形)のどの頂点を基準にするかという指定をします。 GL_FIRST_VERTEX_CONVENTIONもしくは、GL_LAST_VERTEX_CONVENTIONが設定できます。 ここでは、FIRSTの方を指定します。 シェーダコード simple.vert #version 330 struct MaterialParam { vec4 ambient; vec4 diffuse; vec4 specular; float shininess; }; uniform vec3 u_lightPos; uniform MaterialParam u_lightMaterial; uniform MaterialParam u_material; uniform mat4 u_modelMatrix; // モデル・マトリックス uniform mat4 u_viewMatrix; // ビュー・マトリックス uniform mat4 u_projectionMatrix; // 射影・マトリックス in vec3 a_position; in vec3 a_normal; flat out vec4 v_color; // ★outに対してflatを付加★ void main(void) { mat4 modelViewMatrix = u_viewMatrix * u_modelMatrix; vec3 lightPos = vec3(u_viewMatrix * vec4(u_lightPos.xyz,1.0)); mat3 n_mat = mat3( transpose( inverse(modelViewMatrix) ) ); // normal Matrix vec3 P = vec3(modelViewMatrix * vec4(a_position,1.0)); vec3 N = normalize(n_mat * a_normal); vec3 L = normalize(lightPos.xyz - P); // light vector float nDotL = dot(N,L); float diffuseLight = max(nDotL,0.0); vec4 ambient = u_lightMaterial.ambient * u_material.ambient; vec4 diffuse = u_lightMaterial.diffuse * u_material.diffuse * diffuseLight; vec3 V = normalize(-P); //vec3 H = normalize(L+V); // ハーフベクトルによるスペキュラー //float nDotH = pow(max(dot(N,H),0.0), u_material.shininess); vec3 H = reflect(-L,N); // 反射ベクトルによるスペキュラー float nDotH = pow(max(dot(V,H),0.0), u_material.shininess); if (nDotH 0.0) nDotH = 0.0; vec4 specular = u_lightMaterial.specular * u_material.specular * nDotH; v_color = ambient + diffuse + specular; gl_Position = u_projectionMatrix*modelViewMatrix*vec4(a_position.xyz, 1.0); } simple.frag #version 330 flat in vec4 v_color; // ★inに対してflatを付加★ out vec4 fragColor; void main(void) { fragColor = v_color; } Download glsl_flat00.tgz
https://w.atwiki.jp/risc2010/pages/20.html
OpenGL ここを編集
https://w.atwiki.jp/nkym_memo/pages/60.html
OpenGL
https://w.atwiki.jp/zukunashi-yarou/pages/22.html
OpenGL
https://w.atwiki.jp/bambooflow/pages/286.html
SDL - Simple DirectMedia Layer SDL - Simple DirectMedia LayerDownload Compile cmake準備 Empty Project 表示 参考 Download Compile % sudo apt-get install libsdl1.2-dev http //www.libsdl.org/ SDL.lib SDLmain.lib opengl32.lib g++ `sdl-config --cflags --libs` -lGL sample.cpp -o sample cmake準備 CMakeLists.txt # # CMakeFileLists.txt # # cmake . # # 要求するCMakeのバージョン cmake_minimum_required(VERSION 2.6) # build type set(CMAKE_BUILD_TYPE DEBUG) # compile option (DEBUG) set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") set(CMAKE_C_FLAGS_DEBUG "-g -Wall") # compile option (Release) set(CMAKE_CXX_FLAGS_RELEASE "-Wall -O3") set(CMAKE_C_FLAGS_RELEASE "-Wall -O3") # インストール先 # CMAKE_INSTALL_PREFIX(...) ############################################################ set(PROJ_NAME run.x) set(TARGET ${PROJ_NAME}) set(SDL_PATH /usr) # プロジェクト名 project(${PROJ_NAME}) # インクルードパスの追加 include_directories(${SDL_PATH}/include) # ライブラリパスの追加 link_directories(${SDL_PATH}/lib) # 実行ファイルとソースファイル群 add_executable(${TARGET} main.cpp) # ライブラリ target_link_libraries(${TARGET} SDL GL GLU) # マクロ設定 [-D] #add_definitions(-D) Empty Project main.cpp #include cstdio #include cstdlib #include iostream #include SDL/SDL.h #include SDL/SDL_opengl.h #include GL/gl.h #include GL/glu.h static bool initSDL(int width, int height); static void initGL(); static void reshape(GLsizei w, GLsizei h); static void process_events(); static void draw(); bool initSDL(int width, int height) { const SDL_VideoInfo* info; const SDL_Surface *surf; int bpp = 0; if (SDL_Init(SDL_INIT_VIDEO) 0) { std cerr "Video initialization Failed " SDL_GetError() "\n"; SDL_Quit(); return false; } info = SDL_GetVideoInfo(); if (!info) { std cerr "Video query failed " SDL_GetError() "\n"; } bpp = info- vfmt- BitsPerPixel; SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); //atexit(SDL_Quit); surf = SDL_SetVideoMode(width, height, bpp, SDL_OPENGL|SDL_RESIZABLE); if (!surf) { std cerr SDL_GetError() "\n"; SDL_Quit(); return false; } reshape(width, height); return true; } void initGL() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); } void reshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glOrtho(0.0, w, h, 0.0, -1.0, 1.0); } void process_events() { SDL_Surface *surf; SDL_Event event; while (SDL_PollEvent( event)) { switch (event.type) { case SDL_QUIT std exit(1); break; case SDL_KEYDOWN switch (event.key.keysym.sym) { case SDLK_ESCAPE std exit(0); break; default break; } break; case SDL_VIDEORESIZE SDL_FreeSurface(surf); surf = SDL_SetVideoMode(event.resize.w, event.resize.h, 32, SDL_OPENGL|SDL_RESIZABLE); reshape(static_cast GLsizei (event.resize.w), static_cast GLsizei (event.resize.h)); break; } } } void draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glLoadIdentity(); // 四角形を描く glBegin(GL_QUADS); { glColor3f(1.0, 1.0f, 1.0); // white // 4つの頂点を指定 glVertex3f(100.0f, 100.0f, 0); glVertex3f(540.0f, 100.0f, 0); glVertex3f(540.0f, 380.0f, 0); glVertex3f(100.0f, 380.0f, 0); } glEnd(); SDL_GL_SwapBuffers(); } int main(int argc, char* argv[]) { if (!initSDL(640, 480)) { std exit(1); } // initialize OpenGL initGL(); // simLoop while (true) { process_events(); draw(); } return 0; } 表示 参考 http //www.tacoworks.jp/software/SDLdoc-jp/html/index.html
https://w.atwiki.jp/bambooflow/pages/284.html
GLSLで法線マッピング(Normal mapping) dot3バンプマッピング GLSLで法線マッピング(Normal mapping)法線マップについて 法線の変換(メモ) シェーダプログラム まとめ 参考 通常のテクスチャマッピング 法線マッピング 法線マップについて 法線マップを利用したバンプマッピングは、2000年ごろDirectX 8が発表されてプログラマブルシェーダが導入されたころに普及した技術のようです。 法線マップは、法線ベクトルのX,Y,Zが格納されたRGB画像です。 通常の画像ファイルのR,G,Bのところに、法線マップは接線T、従法線B、法線Nを格納します。 法線マップの作成方法は、ツールを使い作成します。 無償でも手に入る手ごろのものにGIMPのpluginがあります。 http //code.google.com/p/gimp-normalmap/ これは色(高さ)情報から法線マップを作成するものです。 使い方はほかのサイトを参考にしてください。 法線の変換(メモ) 法線ベクトルの変換は、頂点や位置ベクトルとは異なり、数学的にはベクトルとしてではなくベクトルに垂直な平面と考えたほうがよいようです。なので、法線ベクトルの変換は垂直な平面の場合の変換ルールにより説明されます。 接線空間の法線をワールド空間に変換する場合は、逆転置行列を使います。 N = transpose( inverse( n ) ); ただし、法線マップはフラグメントシェーダで取り出すため、法線を座標変換すると計算コストがかかります。 よって、法線ベクトルを変換せずに済ませる方法を考えます。 解決方法としては、次の2つ。 法線マップにワールド空間に変換したベクトルを格納する 光線ベクトル、視線ベクトルを接線空間に変換する 1に関しては、動的に動くオブジェクトには適用できない問題があります。 ここでは、2の方法で実装を考えます。 シェーダプログラム いまいち怪しいところが拭いきれていないのですが、とりあえずメモとして残しておきます。 間違いがあれば随時修正ということで。 法線は外部から与えていますが、接線と従法線は内部で適当に生成しています。 接線のルールとしては「法線と貼り付ける法線マップの+x方向を一致させる」らしいのですが、それっぽければいいかというかんじでここでは内部で生成しています。 接線の生成方法は単純で1つ基準となるベクトル(helpvec)を用意し法線との外積をとることで法線に90度のベクトルが生成されます。あとは、法線と接線の外積をとることで従法線が生成できます。 頂点シェーダ #version 330 uniform mat4 modelMatrix; // モデル・マトリックス uniform mat4 viewMatrix; // ビュー・マトリックス uniform mat4 projectionMatrix; // 射影・マトリックス uniform vec3 u_lightPos; // 光線の位置 uniform vec3 u_eyePos; // 視点の位置 in vec3 a_position; in vec3 a_normal; in vec2 a_texcoord0; out vec3 v_viewDirection; out vec3 v_lightDirection; out vec2 v_texcoord; void main(void) { mat4 modelViewMatrix = viewMatrix * modelMatrix; mat3 n_mat = mat3( transpose( inverse(modelViewMatrix) ) ); // normal Matrix vec3 eyePosWorld = (n_mat * u_eyePos); vec3 viewDirWorld = normalize(eyePosWorld - a_position); vec3 lightPosWorld = (n_mat * u_lightPos); vec3 lightDirWorld = normalize(lightPosWorld - a_position); vec3 helpVec = vec3(0.0, 0.0,1.0); vec3 tangent = cross(a_normal, helpVec); if (length(tangent) == 0.0) { tangent = vec3(0.0, 1.0, 0.0); } vec3 binormal = cross(a_normal, tangent); mat3 tangentMat = mat3(tangent, binormal, a_normal); v_viewDirection = viewDirWorld * tangentMat; v_lightDirection = lightDirWorld * tangentMat; v_texcoord = a_texcoord0; gl_Position = projectionMatrix * modelViewMatrix * vec4(a_position.xyz, 1.0); } フラグメントシェーダ 法線マップによる光線反射の計算はフラグメントシェーダ側で行っている。 #version 330 uniform sampler2D s_baseMap; //ベースとなる通常のテクスチャ uniform sampler2D s_bumpMap; //法線マップ in vec3 v_viewDirection; in vec3 v_lightDirection; in vec2 v_texcoord; out vec4 fragColor; void main(void) { vec4 baseColor = texture2D(s_baseMap, v_texcoord); vec3 normal = texture2D(s_bumpMap, v_texcoord).xyz; normal = normalize(normal * 2.0 - 1.0); // -1.0~1.0 vec3 lightDirection = normalize(v_lightDirection); vec3 viewDirection = normalize(v_viewDirection); float nDotL = dot(normal, lightDirection); vec3 reflection = (2.0*normal*nDotL) - lightDirection; float rDotV = max(0.0, dot(reflection, viewDirection)); vec4 ambient = vec4(0.2, 0.2, 0.2, 1.0) * baseColor; vec4 diffuse = vec4(0.8, 0.8, 0.8, 1.0) * nDotL * baseColor; vec4 specular = vec4(1.0, 1.0, 1.0, 1.0) * pow(rDotV, 100.0); fragColor = ambient + diffuse + specular; //fragColor = ambient + diffuse; } ちなみに、以下はベースのテクスチャを単色にしたときの表示結果。 まとめ 今回、ようやく法線マッピングにとりかかることができました。 なかなか思うようにいかなくて試行錯誤しながらようやく形になった感じです。 正直正解というものをよく知らないので、本当にあっているかも微妙です。 まぁなんとなくそれっぽければ。。。 法線マッピングは、ピクセルの光線計算に注目した処理のようです。 なので単純なテクスチャマッピングに比べて立体感は表せるのですが何か物足りなさを感じます。 法線マップは初歩的な技術のようで、発展としては、 視差マッピング(Parallax mapping) 変異マッピング(Displacement mapping) というものがあるようです。 今後、勉強として手を付けてみたいところです。 参考 「OpenGL ES2.0 プログラミングガイド」- 法線マップによるライティング
https://w.atwiki.jp/bambooflow/pages/288.html
gl3w gl3wは、OpenGL3/4のcore profileが提供する機能を手に入れるための最も簡単な方法。 以下のサイトから https //github.com/skaslev/gl3w ダウンロード % git clone https //github.com/skaslev/gl3w.git gl3wをテストする % cd gl3w % ./gl3w_gen.py すると、srcディレクトリにgl3w.cファイルが生成される。 % cd src % gcc -o test test.c gl3w.c -I../include -lglut 実行する。 % ./test 実行がうまくいくと、ランダム(randf)でチカチカする画面が表示される。 サンプル #include stdio.h #include GL3/gl3w.h #include GL/glut.h // ... int main(int argc, char **argv) { glutInit( argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(width, height); glutCreateWindow("cookie"); glutReshapeFunc(reshape); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutSpecialFunc(special); glutMouseFunc(mouse); glutMotionFunc(motion); if (gl3wInit()) { fprintf(stderr, "failed to initialize OpenGL\n"); return -1; } if (!gl3wIsSupported(3, 2)) { fprintf(stderr, "OpenGL 3.2 not supported\n"); return -1; } printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); // ... glutMainLoop(); return 0; } メモ 現状Linuxの環境で動かそうとしたとき、原因不明のSegmentation Fault.が発生した。 原因は、gl3wInit()を呼ぶ前に、glGetString(GL_VERSION)を呼んだことだった。 glewと挙動が異なったため、少しハマってしまった。。
https://w.atwiki.jp/bambooflow/pages/289.html
GLM - OpenGL Mathematics GLMは3DグラフィックスのためのC++ライブラリです。 GLSLのAPIと類似しており扱いやすくなっています。 GLM - OpenGL Mathematicsダウンロード 簡単な使い方 ヘッダファイル 基本Identity(単位行列) Matrix Transformtranslate行列(移動) rotate行列(回転) scale行列(拡大縮小) Matrix Projectionortho frustum perspective Matrix Transform2lookAt Quaternion使い方 フルにSwizzleを使う 2つのベクトルの角度差 2次元ベクトルの回転 ダウンロード http //glm.g-truc.net/ 簡単な使い方 次のヘッダをインクルードします。 #include glm/glm.hpp #include stdio.h #include glm/glm.hpp int main(int argc, char* argv[]) { glm vec3 pos( 1.0, 2.0, 3.0); printf("x=%f, y=%f, z=%f\n", pos.x, pos.y, pos.z); return 0; } vec3へのアクセスはいろいろ準備されています。 たとえば配列だと、pos[0],pos[1],pos[2]で参照できます。 GLMの扱いやすいところは、GLSLとAPIが似ていることと、swizzleが用意されていること。 ヘッダファイル よく使いそうなヘッダファイルは次のとおり。 #include glm/glm.hpp // for translate, rotate, scale #include glm/matrix_transform.hpp // for ortho, frustum, perspective, project #include glm/matrix_projection.hpp // for lookAt, proj2D, proj3D, etc. #include glm/gtx/transform2.hpp // for value_ptr #include glm/gtc/type_ptr.hpp 基本 Identity(単位行列) #include glm/glm.hpp glm mat4 ident = glm mat4(1.0); glLoadIdentity Matrix Transform translate行列(移動) #include glm/gtc/matrix_transform.hpp template typename T tmat4x4 T translate( tmat4x4 T const m, // 元マトリックス tvec3 T const v // 位置(x,y,z) ); 使い方例 #include glm/glm.hpp #include glm/gtc/matrix_transform.hpp float angle; glm vec3 pos(0.0, 3.0, 0.0); // 位置y=3.0 glm mat4 a; ・・・ glm mat4 b = glm translate(a, pos); rotate行列(回転) #include glm/gtc/matrix_transform.hpp template typename T tmat4x4 T rotate( tmat4x4 T const m, // 元マトリックス T const angle, // 回転角(radian) tvec3 T const v // 回転軸(x,y,z) ); 使い方例 #include glm/glm.hpp #include glm/gtc/matrix_transform.hpp float angle; glm vec3 axis(0.0, 1.0, 0.0); // y軸で回転 glm mat4 a; ・・・ glm mat4 b = glm rotate(a, angle, axis); scale行列(拡大縮小) #include glm/gtc/matrix_transform.hpp template typename T tmat4x4 T scale( tmat4x4 T const m, // 元マトリックス tvec3 T const v // スケール(x,y,z) ); 使い方例 #include glm/glm.hpp #include glm/gtc/matrix_transform.hpp glm vec3 size(0.5, 0.5, 0.5); // スケール 1/2に縮小 glm mat4 a; ・・・ glm mat4 b = glm rotate(a, size); Matrix Projection ortho #include glm/glm.hpp #include glm/gtc/matrix_projection.hpp frustum #include glm/glm.hpp #include glm/gtc/matrix_projection.hpp perspective #include glm/glm.hpp #include glm/gtc/matrix_projection.hpp glm mat4 projectionMatrix; void reshape(int w, int h) { glViewport(0, 0, w, h); projectionMatrix = glm perspective(30.0f, (float)w/(float)h, 1.0f, 100.0f); } Matrix Transform2 lookAt template typename T tmat4x4 T lookAt( tvec3 T const eye, tvec3 T const center, tvec3 T const up ); #include glm/glm.hpp #include glm/gtx/transform2.hpp glm mat4 viewMatrix; viewMatrix = glm lookAt( glm vec3(3.0f, 4.0f, 5.0f), // eye pos glm vec3(0.0f, 0.0f, 0.0f), // center pos glm vec3(0.0f, 1.0f, 0.0f) // up ); Quaternion 使い方 #include glm/glm.hpp #include glm/gtc/quaternion.hpp glm quat a, b, c; // Quatanionの乗算 c = glm cross( a, b ); // Quotanionから行列を求める glm mat4 r = glm mat4_cast( c ); フルにSwizzleを使う たとえば、.x, .y, .zや .t, .sといったものはデフォルトで扱えます。 でも.xyzやxyzwなどは設定が必要になります。 #include glm/setup.hpp #define GLM_SWIZZLE GLM_SWIZZLE_FULL #include glm/glm.hpp